#pragma once
#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <functional>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <cstring>
#include "Log.hpp"
#include "ThreadPool.hpp"
#include "Task.hpp"

class TcpServer;
// 线程池的任务队列参数类型
using task_t = std::function<void()>;

// 数据类型，用于传入线程函数
class ThreadData
{
public:
    ThreadData(int sockfd, std::string ip, uint16_t port, TcpServer *s)
        : _sockfd(sockfd), _ip(ip), _port(port), _self(s)
    {
    }

public:
    int _sockfd;
    uint16_t _port;
    std::string _ip;
    TcpServer *_self;
};
// 服务器
class TcpServer
{
public:
    TcpServer(std::string ip, uint16_t port)
        : _ip(ip), _port(port), _listen_socket(-1)
    {
    }
    void InitServer()
    {
        // 创建套接字
        _listen_socket = socket(AF_INET, SOCK_STREAM, 0);
        if (_listen_socket < 0)
        {
            Log(FATAL, "socket create fail...%d:%s", errno, std::strerror(errno));
            exit(1);
        }
        Log(DEBUG, "listensocket create success...");
        int opt = 1;
        setsockopt(_listen_socket, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt)); // 防止偶发性的服务器无法进行立即重启(tcp协议的时候再说)
        // 创建套接字结构体
        struct sockaddr_in native;
        native.sin_family = AF_INET;
        native.sin_addr.s_addr = inet_addr(_ip.c_str());
        native.sin_port = htons(_port);
        // 绑定
        int n = bind(_listen_socket, (struct sockaddr *)&native, sizeof(native));
        if (n < 0)
        {
            Log(FATAL, "bind fail...");
            exit(2);
        }
        else
        {
            Log(DEBUG, "bind success...");
        }

        // 打开监听
        n = listen(_listen_socket, 10);
        if (n < 0)
        {
            Log(FATAL, "listen fail...");
            exit(3);
        }
        else
        {
            Log(DEBUG, "listen success");
        }
    }

    // static void *Handler(void *args)
    // {
    //     ThreadData *td = static_cast<ThreadData *>(args);
    //     pthread_detach(pthread_self()); // 分离自身
    //     td->_self->Service(td->_sockfd, td->_ip);
    //     close(td->_sockfd);
    //     return nullptr;
    // }
    void Start()
    {
        // 创建客户端套接字

        // 接受连接请求，建立连接，获取连接描述符
        while (true)
        {
            struct sockaddr_in client;
            socklen_t len = sizeof(client);
            int sockfd = accept(_listen_socket, (struct sockaddr *)&client, &len);
            if (sockfd < 0)
            {
                Log(DEBUG, "sockfd create false...[%d][%s]", errno, strerror(errno));
            }
           
            uint16_t clientport = ntohs(client.sin_port);
            char clientip[64];
            inet_ntop(AF_INET, &(client.sin_addr), clientip, sizeof(clientip));

  
            Task t(sockfd, clientip, clientport);
            threadpool<Task>::GetInstance()->enqueue(t);
        }
    }

    ~TcpServer() {}

private:
    int _listen_socket;
    std::string _ip;
    uint16_t _port;
};